using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using IndyMosaic.Models;
using IndyMosaic.Models.Blog;
using IndyMosaic.Core.Data;
using System.Web.Security;
using System.Text;
using IndyMosaic.Site.ViewData.Blog;
//using IndyMosaic.Core.Notifications.Blog;
using IndyMosaic.Core.Extensions;
using IndyMosaic.Core.Notifications;

namespace IndyMosaic.Site.Controllers
{
    public class BlogController : Controller
    {

        private IBlogRepository repository { get; set; }

        #region Contructors
        public BlogController()
            : this(new BlogRepository())
        {
        }

        public BlogController(IBlogRepository repository)
        {
            this.repository = repository;
        }
        #endregion

        #region Actions
        #region Blog Entry 
        //
        // GET: /Blog/

        //public ActionResult Index()
        //{
        //    return View(repository.ListLatestTopNEntries(5));
        //}

        public ActionResult Index(int? page)
        {
            const int pageSize = 10;
            var blogEntries = repository.ListAllEntries();
            var paginatedBlogEntries = new PaginatedList<Entry>(blogEntries, (page ?? 0), pageSize);

            return View(paginatedBlogEntries);
        }
        //
        // GET: /Blog/Details/5

        public ActionResult Details(int id)
        {
            Entry entry = repository.GetEntry(id);
            

            if (entry == null)
            {
                return View("NotFound");
            }
            else
            {
                entry.Content = entry.Content.Replace("<##MORE##>", "");
                Comment comment = new Comment();
                if (Request.IsAuthenticated)
                {
                    comment.EmailAddress = Membership.GetUser().Email;
                }
                return View("Details", new Details(entry, comment, GetDetailComments(entry)));
            }
        }

        public ActionResult Author(Guid authorUserID)
        {
            var entries = repository.ListAllByAuthor(authorUserID);
            if (Membership.GetUser().GetUserIDAsGuid() != authorUserID)
            {
                entries = entries.Where(e => e.DatePublished != null && e.DatePublished < DateTime.Now);
            }
            return View(entries);
        }

        
       
        #endregion

        #region Comments
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult CreateComment(FormCollection colletion)
        {
            Comment newComment = new Comment();
            int entryId = int.Parse(colletion["EntryID"]);
            try
            {
                newComment.EntryID = entryId;
                newComment.DatePosted = DateTime.Now;
                newComment.IPAddress = Request.UserHostAddress;
                if (AutoApproveComment())
                {
                    newComment.SetApprovalInfo(Membership.GetUser().GetUserIDAsGuid(), ApprovalStatus.Approved);
                    //SimpleNotifier notifier = SimpleNotifierFactory.GetNotifier(newComment);
                    //notifier.NotifySubscribers();
                }

                UpdateModel(newComment);
                repository.Add(newComment);
                repository.Save();

                

                return RedirectToAction("Details", new { id = entryId });
            }
            catch
            {
                ModelState.AddRuleViolations(newComment.GetRuleViolations());
                Entry entry = repository.GetEntry(entryId);
                return View("Details", new Details(entry, newComment, GetDetailComments(entry)));
            }
        }

        

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveComment(FormCollection collection)
        {
            int commentID = int.Parse(collection["CommentID"]);
            ApprovalStatus status = (ApprovalStatus)Enum.Parse(typeof(ApprovalStatus), collection["ApprovalStatus"]);

            Comment comment = repository.GetComment(commentID);
            if (comment == null)
            {
                return View("NotFound");
            }
            else
            {
                comment.SetApprovalInfo(Membership.GetUser().GetUserIDAsGuid(), status);
                if (status == ApprovalStatus.Approved)
                {
                    //SimpleNotifier notifier = SimpleNotifierFactory.GetNotifier(comment);
                    //notifier.NotifySubscribers();
                }
                UpdateModel(comment);
            }
            repository.Save();

            return RedirectToAction("Details", new { id = comment.EntryID });
        }
        #endregion

        #region Syndication
        public ActionResult RSS()
        {
            var entries = repository.ListLatestTopNEntries(10);
            StringBuilder sb = new StringBuilder(Request.Url.ToString());
            sb.Replace("RSS", "Details/{0}");
            return Content(repository.GetFeed(entries, sb.ToString(), Url));
        }
        #endregion

        #region Secured Actions
        #region Blog Entry
        //
        // GET: /Blog/Create
        [Authorize]
        public ActionResult Create()
        {
            Entry entry = new Entry();
            entry.AuthorName = HttpContext.Profile["FullName"] as string;
            return View(entry);
        }

        //
        // POST: /Blog/Create
        [Authorize]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(FormCollection collection)
        {
            Entry entry = new Entry();
            if (collection["published"] == "Publish")
            {
                entry.DatePublished = DateTime.Now;
            }
            entry.UserID = Membership.GetUser().GetUserIDAsGuid();
            try
            {
                UpdateModel(entry);
                repository.Add(entry);
                repository.Save();

                return RedirectToAction("Details", new { id = entry.ID });
            }
            catch
            {
                ModelState.AddRuleViolations(entry.GetRuleViolations());
                return View(entry);
            }
        }

        //
        // GET: /Blog/Edit/5

        [Authorize]
        public ActionResult Edit(int id)
        {
            Entry entry = repository.GetEntry(id);
            if (ValidCreateEditAccess(entry))
            {
                return View("NotAuthorized");
            }
            if (entry == null)
            {
                return View("NotFound");
            }
            else
            {
                return View(entry);
            }
        }

        //
        // POST: /Blog/Edit/5
        [Authorize]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, FormCollection collection)
        {
            Entry entry = repository.GetEntry(id);
            if (ValidCreateEditAccess(entry))
            {
                return View("NotAuthorized");
            }
            try
            {
                if (collection["published"] == "Publish" && entry.DatePublished == null)
                {
                    entry.DatePublished = DateTime.Now;
                }
                string[] allowedProperties = new[] { "Title", "AuthorName", "Content" };
                UpdateModel(entry, allowedProperties);
                repository.Save();

                return RedirectToAction("Details", new { id = id });
            }
            catch
            {
                ModelState.AddRuleViolations(entry.GetRuleViolations());

                return View(entry);
            }
        }
        #endregion
        #endregion

        #endregion

        private static IEnumerable<Comment> GetDetailComments(Entry entry)
        {
            IEnumerable<Comment> comments = entry.Comments;
            if (!Membership.GetUser().IsCommentApprover())
            {
                comments = entry.ApprovedComments;
            }
            return comments;
        }
        private bool ValidCreateEditAccess(Entry entry)
        {
            Guid userId = Membership.GetUser().GetUserIDAsGuid();
            return entry.UserID != userId  || !Roles.IsUserInRole("Administrator");
        }
        private bool AutoApproveComment()
        {
            List<string> validRoles = new List<string>();
            validRoles.Add("Blogger");
            validRoles.Add("Content Provider");
            validRoles.Add("Administrator");

            foreach (string roleName in validRoles)
            {
                if (Roles.IsUserInRole(roleName))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
